package cn.sdormitory.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.sdormitory.attendance.dao.AttendanceRulesDao;
import cn.sdormitory.attendance.entity.AttendanceRules;
import cn.sdormitory.basedata.dao.BClassDao;
import cn.sdormitory.basedata.dao.BStudentDao;
import cn.sdormitory.basedata.entity.BClass;
import cn.sdormitory.basedata.entity.BStudent;
import cn.sdormitory.basedata.vo.BClassVo;
import cn.sdormitory.basedata.vo.BStudentListVo;
import cn.sdormitory.common.constant.CommonConstant;
import cn.sdormitory.common.exception.ApiException;
import cn.sdormitory.morningExercises.entity.MorningExercises;
import cn.sdormitory.morningExercises.vo.AppMorningExercisesCountVO;
import cn.sdormitory.retention.AppRetentionCountVO;
import cn.sdormitory.retention.DormitoryRetention;
import cn.sdormitory.service.AppAttenceService;
import cn.sdormitory.service.AppMorningExercisesService;
import cn.sdormitory.service.AppRetentionService;
import cn.sdormitory.smartclass.dao.ClassAttenceDao;
import cn.sdormitory.smartdor.dao.SdAttenceDao;
import cn.sdormitory.smartdor.entity.DeptDataBoardSummary;
import cn.sdormitory.smartdor.entity.DeptDormitorySummary;
import cn.sdormitory.smartdor.entity.SdAttence;
import cn.sdormitory.smartdor.entity.SdStudentAttenceDetail;
import cn.sdormitory.smartdor.vo.DormitoryAttenceVo;
import cn.sdormitory.smartdor.vo.SdAttenceVo;
import cn.sdormitory.sys.dao.SysDeptDao;
import cn.sdormitory.sys.dao.SysDictDetailDao;
import cn.sdormitory.sys.dao.SysUserDao;
import cn.sdormitory.sys.entity.SysDictDetail;
import cn.sdormitory.sys.entity.SysUser;
import cn.sdormitory.sys.enums.StatusEnums;
import cn.sdormitory.sys.service.SysUserRoleService;
import cn.sdormitory.violative.dao.ViolationPatrolDao;
import cn.sdormitory.violative.entity.ViolationPatrol;
import cn.sdormitory.workflow.dao.ViolationApplyDao;
import cn.sdormitory.workflow.entity.ViolationApply;
import cn.sdormitory.workflow.service.ViolationApplyService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

/**
 * @创建人：zhouyang
 * @创建时间：2020/12/30 11:48
 * @version：V1.0
 */
@Service
public class AppAttenceServiceImpl extends ServiceImpl<SdAttenceDao, SdAttence> implements AppAttenceService {
    @Resource
    private SdAttenceDao sdAttenceDao;
    @Resource
    private BClassDao bClassDao;
    @Resource
    private SysDictDetailDao sysDictDetailDao;
    
    @Resource
    private SysUserDao sysUserDao;
    
    @Resource
    private SysUserRoleService sysUserRoleService;
    
    @Resource
    private SysDeptDao sysDeptDao;

    @Autowired
    AttendanceRulesDao attendanceRulesDao;

    @Autowired
    ClassAttenceDao classAttenceDao;

    @Autowired
    BStudentDao bStudentDao;
    
    @Resource
    private ViolationPatrolDao violationPatrolDao;
    
    @Resource
    private ViolationApplyService violationApplyService;
    
    @Resource
    private ViolationApplyDao violationApplyDao;
    
    @Resource
    private AppMorningExercisesService appMorningExercisesService;
    
    @Resource
    private AppRetentionService appRetentionService;

    @Override
    public List<DormitoryAttenceVo> getAppDorAttence() {
        Date checkDate;
        if (new Date().getHours() < CommonConstant.ATTENDANCE_TIME_INT) {
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.DATE, -1);
            Date d = cal.getTime();
            checkDate=d;
        }else{
            Calendar cal = Calendar.getInstance();
            Date d = cal.getTime();
            checkDate=d;
        }
        return sdAttenceDao.getAppDorAttence(checkDate);

    }

    @Override
    public List<SdAttenceVo> getAppAbsenceStudent(Date checkDate) {
        if(new Date().getHours() < CommonConstant.ATTENDANCE_TIME_INT && ("".equals(checkDate) || checkDate == null)){
            Calendar cal= Calendar.getInstance();
            cal.add(Calendar.DATE,-1);
            Date d=cal.getTime();
            checkDate=d;
        }
        return sdAttenceDao.getAppAbsenceStudent(checkDate);
    }

    @Override
    public SdAttence getAttenceById(Long id) {
        return sdAttenceDao.selectOne(new LambdaQueryWrapper<SdAttence>().eq(SdAttence::getId,id));
    }

    @Override
    public BClass getClassById(Long id) {
        return bClassDao.selectById(id);
    }

    @Override
    public List<BClass> getClassListAll() {
       return bClassDao.selectList(new LambdaQueryWrapper<BClass>().eq(BClass::getStatus,CommonConstant.VALID_STATUS));
    }

    @Override
    public List<SysDictDetail> selectDictDataByType(String dictType) {
        return sysDictDetailDao.selectList(new LambdaQueryWrapper<SysDictDetail>()
                .eq(SysDictDetail::getDictType, dictType)
                .eq(SysDictDetail::getStatus, StatusEnums.ENABLE.getKey()));
    }

    @Override
    public int insert(SdAttence sdAttence) {
        return this.baseMapper.insert(sdAttence);
    }

    @Override
    public List<Map<String, Object>> getAllClassAttendanceByClsTeachId(Map<String, String> params) throws ApiException{
        Long clsTeacherId = Long.valueOf(params.get("clsTeacherId"));
        String accessDate = params.get("assessDate");
        LambdaQueryWrapper<BClass> clsWrapper = new LambdaQueryWrapper<>();
        clsWrapper.eq(BClass::getClassTeacherId,clsTeacherId);
        List<BClass> bClassList = bClassDao.selectList(clsWrapper);
        if(bClassList.size() <= 0 || bClassList == null){
            throw new ApiException("当前老师未带班");
        }

        List<Map<String, Object>> result = new ArrayList<>();

        //获取当前班级的详细考勤规则
        List<AttendanceRules> allAttendanceRules= attendanceRulesDao.getAllAttendanceRulesDetailInfo();

        for(BClass bClass : bClassList){

            //当前班级学生人数
            LambdaQueryWrapper<BStudent> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(BStudent::getClassId,bClass.getId());
            List<BStudent> bStudentList = bStudentDao.selectList(wrapper);
            int clsCount = bStudentList.size();

            Map<String, Object> classData = new HashMap<>();
            Map<String, Object> chartData = new HashMap<>();
            List<String> categories = new ArrayList<>();
            List<Object> series = new ArrayList<>();

            if(bClass.getClassAttendanceRules() == null){
                continue;
            }
            String[] rules = bClass.getClassAttendanceRules().split(",");

            List<AttendanceRules> clsRulesList = new ArrayList<>();
            for (int i = 0; i < rules.length; i++) {
                for(AttendanceRules item : allAttendanceRules){
                    if(item.getId() == Long.valueOf(rules[i])){
                        clsRulesList.add(item);
//                        categories.add(item.getTimeSlotLabel());
                    }
                }
            }

            //排序
            Collections.sort(clsRulesList, Comparator.comparing(AttendanceRules::getAttendanceStartTime));
            for(AttendanceRules item : clsRulesList){
                categories.add(item.getTimeSlotLabel());
            }

            chartData.put("categories",categories);

            //正常
            Map<String,Object> normalSeries = new HashMap<>();
            normalSeries.put("name","正常");
            List<Object> normalData = new ArrayList<>();
            for(AttendanceRules item : clsRulesList){
                int normalCount = classAttenceDao.getClsAttenceCountByCondition(bClass.getId(),accessDate,
                        "1",item.getTimeSlot());
                normalData.add(normalCount);
            }
            normalSeries.put("data",normalData);

            //迟到
            Map<String,Object> lateSeries = new HashMap<>();
            lateSeries.put("name","迟到");
            List<Object> lateData = new ArrayList<>();
            for(AttendanceRules item : clsRulesList){
                int lateCount = classAttenceDao.getClsAttenceCountByCondition(bClass.getId(),accessDate,
                        "2",item.getTimeSlot());
                lateData.add(lateCount);
            }
            lateSeries.put("data",lateData);

            //请假
            Map<String,Object> leaveSeries = new HashMap<>();
            leaveSeries.put("name","请假");
            List<Object> leaveData = new ArrayList<>();
            for(AttendanceRules item : clsRulesList){
                int leaveCount = classAttenceDao.getClsAttenceCountByCondition(bClass.getId(),accessDate,
                        "3",item.getTimeSlot());
                leaveData.add(leaveCount);
            }
            leaveSeries.put("data",leaveData);

            //未打卡
            Map<String,Object> unClockSeries = new HashMap<>();
            unClockSeries.put("name","未打卡");
            List<Object> unClockData = new ArrayList<>();
            for(AttendanceRules item : clsRulesList){
                int normalCount = classAttenceDao.getClsAttenceCountByCondition(bClass.getId(),accessDate,
                        "1",item.getTimeSlot());
                int lateCount = classAttenceDao.getClsAttenceCountByCondition(bClass.getId(),accessDate,
                        "2",item.getTimeSlot());
                int leaveCount = classAttenceDao.getClsAttenceCountByCondition(bClass.getId(),accessDate,
                        "3",item.getTimeSlot());

                int unClockCount = clsCount - normalCount - lateCount - leaveCount;
                unClockData.add(unClockCount);
            }
            unClockSeries.put("data",unClockData);

            series.add(normalSeries);
            series.add(lateSeries);
            series.add(leaveSeries);
            series.add(unClockSeries);

            chartData.put("series",series);

            classData.put("classId",bClass.getId());
            classData.put("className",bClass.getClassName());
            classData.put("chartData",chartData);
            //返回数据
            result.add(classData);
        }
        return result;
    }
    
    @Override
    public List<BStudentListVo> getDormitoryUnClockStu(String userId, String checkDate, String classId) {
        // 根据用户id查询部门id
        SysUser sysUser = sysUserDao.selectById(userId);
        
        Long deptId = sysUser.getDeptId();
        List<BStudentListVo> attences = sdAttenceDao.getAbsenceStudentsByCheckDateAndDeptId(checkDate, String.valueOf(deptId), classId);
        
        return attences;
    }
    
    @Override
    public List<BStudentListVo> getWeekendUnClockStu(String userId, String checkDate, String classId) {
        // 根据用户id查询部门id
        SysUser sysUser = sysUserDao.selectById(userId);
        
        Long deptId = sysUser.getDeptId();
        List<BStudentListVo> attences = sdAttenceDao.getWeekendAbsenceStudentsByCheckDateAndDeptId(checkDate, String.valueOf(deptId), classId);
        
        return attences;
    }
    
    @Override
    public List<DeptDormitorySummary> getDeptDormitorySummary(String userId, String accessDate, String operateType) {
        // 根据用户id查询部门id
        SysUser sysUser = sysUserDao.selectById(userId);
    
        List<BClassVo> classList = getbClassVos(userId);
        
        List<Long> classIds = classList.stream().map(BClassVo::getClassId).collect(Collectors.toList());
        
        // 查询班级下面的所有未毕业的学生
        LambdaQueryWrapper<BStudent> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BStudent::getIsGraduated, "0");
        queryWrapper.in(BStudent::getClassId, classIds);
        List<BStudent> deptStudents = bStudentDao.selectList(queryWrapper);
        
        // 查询出当前日期所有未打卡的学生数据  包含走读生和住宿生
        List<SdStudentAttenceDetail> allRecords = new ArrayList<>();
        if (operateType.equals("dormitory")) {
            allRecords = sdAttenceDao.getAllDormitoryRecords(accessDate);
        }
        
        if (operateType.equals("weekend")) {
            allRecords = sdAttenceDao.getAllWeekendRecords(accessDate);
        }
//        List<SdAttence> allTodayRecords = sdAttenceDao.getAllTodayRecords(accessDate);
    
        List<DeptDormitorySummary> dormitorySummaries = new CopyOnWriteArrayList<>();
        long start = System.currentTimeMillis();
        List<SdStudentAttenceDetail> finalAllRecords = allRecords;
        classList.parallelStream().forEach(bClass -> {
            DeptDormitorySummary deptDorSummary = new DeptDormitorySummary();
            deptDorSummary.setClassId(bClass.getClassId());
            deptDorSummary.setClassName(bClass.getClassName());
            deptDorSummary.setDeptId(bClass.getDeptId());
    
            // 班级人数
            List<BStudent> students = deptStudents.stream().filter(deptStu -> deptStu.getClassId().equals(bClass.getClassId())).collect(Collectors.toList());
            deptDorSummary.setClassPerCount(String.valueOf(students.size()));
            // 住宿生人数
            List<BStudent> liveInStudent = students.stream().filter(bStudent -> bStudent.getStatus().equals("1")).collect(Collectors.toList());
            deptDorSummary.setBoarderStuCount(String.valueOf(liveInStudent.size()));
            // 请假人数
            List<SdStudentAttenceDetail> leaveStudentListVos = finalAllRecords.stream()
                    .filter(sdAttence -> sdAttence.getClassId().equals(String.valueOf(bClass.getClassId())) && sdAttence.getAttenceStatus().equals("4") && sdAttence.getStatus().equals("1")).collect(Collectors.toList());
//            List<BStudentListVo> leaveStudentListVos = sdAttenceDao.getAttenceStusByClassId(bClass.getClassId(), accessDate, "4");
            deptDorSummary.setLeavePerCount(String.valueOf(0));
            if (CollectionUtil.isNotEmpty(leaveStudentListVos)) {
                deptDorSummary.setLeavePerCount(String.valueOf(leaveStudentListVos.size()));
            }
            // 实到人数
            List<SdStudentAttenceDetail> clockInStus = finalAllRecords.stream()
                    .filter(sdAttence -> sdAttence.getClassId().equals(String.valueOf(bClass.getClassId())) && sdAttence.getAttenceStatus().equals("1")).collect(Collectors.toList());
//            List<BStudentListVo> clockInStus = sdAttenceDao.getAttenceStusByClassId(bClass.getClassId(), accessDate, "1");
            deptDorSummary.setClockInPerCount(String.valueOf(0));
            if (CollectionUtil.isNotEmpty(clockInStus)) {
                deptDorSummary.setClockInPerCount(String.valueOf(clockInStus.size()));
            }
            // 未到人数
            List<SdStudentAttenceDetail> notClockStus = finalAllRecords.stream()
                    .filter(sdAttence -> sdAttence.getClassId().equals(String.valueOf(bClass.getClassId())) && sdAttence.getAttenceStatus().equals("2")).collect(Collectors.toList());
//            List<BStudentListVo> notClockStus = sdAttenceDao.getAttenceStusByClassId(bClass.getClassId(), accessDate, "2");
            deptDorSummary.setUnClockPerCount(String.valueOf(0));
            if (CollectionUtil.isNotEmpty(notClockStus)) {
                deptDorSummary.setUnClockPerCount(String.valueOf(notClockStus.size()));
            }
    
            // 应到人数
            deptDorSummary.setNeedClockCount(String.valueOf(liveInStudent.size() - leaveStudentListVos.size()));
            double ratio = Double.parseDouble(deptDorSummary.getClockInPerCount())/Double.parseDouble(deptDorSummary.getNeedClockCount()) * 100;
            deptDorSummary.setAttendanceRate("出勤率:" + String.format("%.2f", ratio) + "%");
    
            dormitorySummaries.add(deptDorSummary);
        });

        // 排序
        Map<String, List<DeptDormitorySummary>> collect = dormitorySummaries.stream().collect(Collectors.groupingBy(DeptDormitorySummary::getDeptId));
        TreeMap<String, List<DeptDormitorySummary>> treeMap = new TreeMap<>(collect);
    
        List<DeptDormitorySummary> resultList = new ArrayList<>();
        for (Map.Entry<String, List<DeptDormitorySummary>> stringListEntry : treeMap.entrySet()) {
            List<DeptDormitorySummary> value = stringListEntry.getValue();
            List<DeptDormitorySummary> sortList = value.stream().sorted(Comparator.comparing(DeptDormitorySummary::getClassName, Comparator.nullsFirst(String::compareTo))).collect(Collectors.toList());
            resultList.addAll(sortList);
        }
    
//        List<DeptDormitorySummary> deptDormitorySummaryList = dormitorySummaries.stream().sorted(Comparator.comparing(DeptDormitorySummary::getClassId, Comparator.nullsFirst(Long::compareTo))).collect(Collectors.toList());
        long end = System.currentTimeMillis();
        System.out.println("耗时："+ (end-start)/1000 + "s.---------------------------");
        return resultList;
    }
    
    private List<BClassVo> getbClassVos(String userId) {
        boolean isDeptManager = false ; //是否部门经理
        List<Long> roleIdList = sysUserRoleService.listRoleIdByUserId(Long.valueOf(userId));
        for (Long roleId : roleIdList) {
            if(roleId == 2) {
                isDeptManager = true ;
                break;
            }
        }
        
        List<BClassVo> classList = new ArrayList<>();
        if(isDeptManager) {
            SysUser user = sysUserDao.selectById(userId);
            List<Long> deptIds = sysDeptDao.getAllChildByParent(user.getDeptId());
            //classList = classDao.getAppClassDeptByClaId(user.getDeptId());
            classList = bClassDao.getAppClassByDeptIds(deptIds);
        } else {
            // 获取班主任下所有班级
            classList = bClassDao.getAppClassListByTeaId(Long.valueOf(userId));
        }
        return classList;
    }
    
    @Override
    public List<BStudentListVo> getStuListByType(String classId, String accessDate, String type) {
        List<BStudentListVo> studentListVos = new ArrayList<>();
        switch (type) {
            case "unclock":
                // 获取未考勤学生列表
                studentListVos = sdAttenceDao.getAttenceStusByClassId(Long.valueOf(classId), accessDate, "2");
                break;
            case "leave":
                // 获取当日请假学生列表
                studentListVos = sdAttenceDao.getAttenceStusByClassId(Long.valueOf(classId), accessDate, "4");
                break;
            case "dormitory":
                // 获取住宿学生列表
                studentListVos = bStudentDao.getDormitoryStudentListByClassId(classId);
//                studentListVos = sdAttenceDao.getAttenceStusByClassId(Long.valueOf(classId), accessDate, "4");
                break;
            case "inclcok":
                // 获取实到学生列表
                studentListVos = sdAttenceDao.getAttenceStusByClassId(Long.valueOf(classId), accessDate, "1");
                break;
        }
        return studentListVos;
    }
    
    @Override
    public List<BStudentListVo> getWeekendStuListByType(String classId, String accessDate, String type) {
        List<BStudentListVo> studentListVos = new ArrayList<>();
        switch (type) {
            case "unclock":
                // 获取未考勤学生列表
                studentListVos = sdAttenceDao.getWeekendAttenceStusByClassId(Long.valueOf(classId), accessDate, "2");
                break;
            case "leave":
                // 获取当日请假学生列表
                studentListVos = sdAttenceDao.getWeekendAttenceStusByClassId(Long.valueOf(classId), accessDate, "4");
                break;
            case "dormitory":
                // 获取住宿学生列表
                studentListVos = bStudentDao.getDormitoryStudentListByClassId(classId);
//                studentListVos = sdAttenceDao.getAttenceStusByClassId(Long.valueOf(classId), accessDate, "4");
                break;
            case "inclcok":
                // 获取实到学生列表
                studentListVos = sdAttenceDao.getWeekendAttenceStusByClassId(Long.valueOf(classId), accessDate, "1");
                break;
        }
        return studentListVos;
    }
    
    public static void main(String[] args) {
        String formatDate = DateUtil.formatDateTime(new Date());
        System.out.println(formatDate);
        
        DateTime time = DateUtil.offsetDay(new Date(), -1);
        String date = DateUtil.formatDate(time);
        System.out.println(date);
    }
    
    @Override
    public List<DeptDataBoardSummary> getMonthlyStatisticsData(String userId, String type) {
        // 获取月份 当前月份之前的12个月
        List<String> yearAndMonth = getYearAndMonth();
        List<DeptDataBoardSummary> deptDataBoardSummaries = new ArrayList<>();
    
        List<BClassVo> bClassVos = getbClassVos(userId);
        List<Long> classIds = bClassVos.stream().map(BClassVo::getClassId).collect(Collectors.toList());
        for (String month : yearAndMonth) {
            String accessDate = month;
    
            DeptDataBoardSummary deptDataBoardSummary = new DeptDataBoardSummary();
            deptDataBoardSummary.setMonthly(month);
            // 宿舍考勤
            List<SdStudentAttenceDetail> dormitory =  sdAttenceDao.getMonthlyAttenceStatisticsData(classIds, accessDate, "2");
            deptDataBoardSummary.setDormitorySummary(String.valueOf(dormitory.size()));
            // 周末考勤
            List<SdStudentAttenceDetail> weekendDormitory =  sdAttenceDao.getMonthlyWeekendStatisticsData(classIds, accessDate, "2");
            deptDataBoardSummary.setWeekendSummary(String.valueOf(weekendDormitory.size()));
            // 滞留人数
            List<DormitoryRetention> retentions =  appRetentionService.getMonthlyStatisticsRetention(classIds, accessDate);
            deptDataBoardSummary.setRetentionSummary(String.valueOf(retentions.size()));
            // 早操人数
            List<MorningExercises> morningExercises = appMorningExercisesService.getMonthlyStatisticsMorningExercises(classIds, accessDate);
            deptDataBoardSummary.setMorningSummary(String.valueOf(morningExercises.size()));
            // 日常违纪
            List<ViolationPatrol> violationCount = violationPatrolDao.getMonthlyViolationCount(accessDate, classIds);
            deptDataBoardSummary.setDayViolationSummary(String.valueOf(violationCount.size()));
            // 宿舍违纪
            List<ViolationApply> violationStatistics = violationApplyDao.getMonthlyViolationStatistics(accessDate, classIds);
            deptDataBoardSummary.setNightViolationSummary(String.valueOf(violationStatistics.size()));
    
            deptDataBoardSummaries.add(deptDataBoardSummary);
        }
        
        return deptDataBoardSummaries;
    }
    
    private List<String> getYearAndMonth() {
        List<String> inventoryDateList = new ArrayList<>();
        LocalDate currentDate = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
        String currentYearMonth = currentDate.format(formatter);
        inventoryDateList.add(currentYearMonth);
        for (int i = 0; i < 5; i++) {
            // 减去一个月
            currentDate = currentDate.minusMonths(1);
            String yearMonth = currentDate.format(formatter);
            inventoryDateList.add(yearMonth);
        }
        // 对已排序的列表进行逆序排序
//        Collections.reverse(inventoryDateList);
        return inventoryDateList;
    }
    
    @Override
    public DeptDormitorySummary getAttenceStatisticalData(String userId, String accessDate, String type) {
        List<BClassVo> bClassVos = getbClassVos(userId);
        List<Long> classIds = bClassVos.stream().map(BClassVo::getClassId).collect(Collectors.toList());
        
        // 获取部门下所有住宿学生
        LambdaQueryWrapper<BStudent> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BStudent::getIsGraduated, "0");
        queryWrapper.eq(BStudent::getStatus, "1");
        queryWrapper.in(BStudent::getClassId, classIds);
        List<BStudent> deptStudents = bStudentDao.selectList(queryWrapper);
        
        
        DeptDormitorySummary deptDormitorySummary = new DeptDormitorySummary();
        List<SdStudentAttenceDetail> dormitory = new ArrayList<>();
        if (type.equals("dormitory")) {
            dormitory = sdAttenceDao.getAllDormitoryRecordsByClassIds(classIds, accessDate, null);
        }
        
        if (type.equals("weekend")) {
            dormitory = sdAttenceDao.getAllWeekendRecordsByClassIds(classIds, accessDate, null);
        }
    
        List<SdStudentAttenceDetail> unclockCount = dormitory.stream().filter(sdAttence -> sdAttence.getAttenceStatus().equals("2")).collect(Collectors.toList());
        List<SdStudentAttenceDetail> leaveCount = dormitory.stream().filter(sdAttence -> sdAttence.getAttenceStatus().equals("4")).collect(Collectors.toList());
        List<SdStudentAttenceDetail> clockCount = dormitory.stream().filter(sdAttence -> sdAttence.getAttenceStatus().equals("1")).collect(Collectors.toList());
        
        deptDormitorySummary.setUnClockPerCount(String.valueOf(unclockCount.size()));
        deptDormitorySummary.setLeavePerCount(String.valueOf(leaveCount.size()));
        deptDormitorySummary.setClockInPerCount(String.valueOf(clockCount.size()));
        deptDormitorySummary.setNeedClockCount(String.valueOf(deptStudents.size() - leaveCount.size()));
        double ratio = Double.parseDouble(deptDormitorySummary.getClockInPerCount())/Double.parseDouble(deptDormitorySummary.getNeedClockCount()) * 100;
        deptDormitorySummary.setAttendanceRate("出勤率: " + String.format("%.2f", ratio) + "%");
    
        return deptDormitorySummary;
    }
    
    @Override
    public DeptDataBoardSummary getAttenceBoardData(String userId, String type) {
        String accessDate = DateUtil.formatDateTime(new Date());
        if (type.equals("yesterday")) {
            DateTime time = DateUtil.offsetDay(new Date(), -1);
            accessDate = DateUtil.formatDate(time);
        }
        List<BClassVo> bClassVos = getbClassVos(userId);
        List<Long> classIds = bClassVos.stream().map(BClassVo::getClassId).collect(Collectors.toList());
        
        // 宿舍未考勤统计
        List<SdStudentAttenceDetail> dormitory =  sdAttenceDao.getAllDormitoryRecordsByClassIds(classIds, accessDate, "2");
        DeptDataBoardSummary deptDataBoardSummary = new DeptDataBoardSummary();
        if (CollectionUtil.isEmpty(dormitory)) {
            deptDataBoardSummary.setDormitorySummary(String.valueOf(0));
        } else {
            deptDataBoardSummary.setDormitorySummary(String.valueOf(dormitory.size()));
        }
        
        // 周末未打卡人数统计
        List<SdStudentAttenceDetail> weekend = sdAttenceDao.getAllWeekendRecordsByClassIds(classIds, accessDate, "2");
        if (CollectionUtil.isEmpty(weekend)) {
            deptDataBoardSummary.setWeekendSummary(String.valueOf(0));
        } else {
            deptDataBoardSummary.setWeekendSummary(String.valueOf(weekend.size()));
        }
        
        // 滞留人数统计
        List<AppRetentionCountVO> retentionCount = appRetentionService.getAppRetentionCount(Long.parseLong(userId), accessDate);
        if (CollectionUtil.isEmpty(retentionCount)) {
            deptDataBoardSummary.setRetentionSummary(String.valueOf(0));
        } else {
            Long unRetentionCount = 0L;
            for (AppRetentionCountVO appRetentionCountVO : retentionCount) {
                unRetentionCount = unRetentionCount + appRetentionCountVO.getRetentionNum();
            }
            deptDataBoardSummary.setRetentionSummary(String.valueOf(unRetentionCount));
        }
    
        // 早操未打卡人数统计
        List<AppMorningExercisesCountVO> exercisesCount = appMorningExercisesService.getAppMorningExercisesCount(Long.parseLong(userId), accessDate);
        if (CollectionUtil.isEmpty(exercisesCount)) {
            deptDataBoardSummary.setMorningSummary(String.valueOf(0));
        } else {
            Long exerciseNotClockPer = 0L;
            for (AppMorningExercisesCountVO exercisesCountVO : exercisesCount) {
                exerciseNotClockPer = exerciseNotClockPer + exercisesCountVO.getExercisesNum();
            }
            deptDataBoardSummary.setMorningSummary(String.valueOf(exerciseNotClockPer));
        }
        // 白天违纪统计
        Integer dayViolationCount = violationPatrolDao.getDayViolationCount(accessDate, classIds);
        deptDataBoardSummary.setDayViolationSummary(String.valueOf(dayViolationCount));
        
        // 晚上违纪统计
        List<Map<String, String>> violationStatistics = violationApplyService.getViolationStatistics(accessDate, accessDate);
        Integer NightViolationCount = 0;
        for (Map<String, String> violationStatistic : violationStatistics) {
            String count = violationStatistic.get("violationCount");
            NightViolationCount += Integer.parseInt(count);
        }
        deptDataBoardSummary.setNightViolationSummary(String.valueOf(NightViolationCount));
        
        return deptDataBoardSummary;
    }
}
